home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
- * use is allowed under the terms of the DICE-LICENSE FILE,
- * DICE-LICENSE.TXT.
- */
- /*
- * $Id: romable.c,v 30.326 1995/12/24 06:13:05 dice Exp dice $
- *
- * Romable exefile -o outfile [-o outfile2] [-pi] [-C addr -D addr]
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #ifdef AMIGA
- #include <lib/version.h>
- #else
- #include <suplib/memory.h>
- #include <include/lib/version.h>
- #include <unistd.h>
- #endif
-
- #define D(x) ; /* Debugging Disabled */
- /* #define D(x) x; // Debugging Enabled */
-
- /* #define BSS_IN_OUTPUT_FILE // Write zeros to output file for BSS */
-
- long NumHunks;
- long FirstHunk;
- long LastHunk;
-
- long CodeStart;
- long DataStart;
- short DataStartAfterCode = 0;
- char DataStartSpecified; /* flag, argument specified */
- char CodeStartSpecified; /* flag, argument specified */
- char PIOpt; /* -pi (position independent) */
-
- int _bufsiz = 8192; /* Buffered file I/O */
-
- typedef unsigned char ubyte;
-
- /*
- ** One of these is allocated per hunk in the file.
- */
- typedef struct {
- long Type; /* AmigaDOS hunk type */
- long Len; /* Initialized data length only */
- long Pc;
- char *Data; /* Allocated memory for hunk */
- } Hunk;
-
- Hunk *Hunks;
-
- long fgetl(FILE *);
- void LoadHeaderInfo(FILE *);
- void ScanHunks(FILE *);
- void RelocHunks(FILE *);
- void DumpHunks(FILE *, FILE *);
- int fwrite_2(int, FILE *, FILE *, char *, long);
-
- int
- main(int ac, char **av)
- {
- short i;
- char *inFile = NULL;
- char *outFile1= NULL;
- char *outFile2= NULL;
- FILE *fi;
- FILE *fo1;
- FILE *fo2 = NULL;
-
-
- if (ac == 1 || ( ac == 2 && *av[1]=='?' ) ) {
- puts("Romable input.exe -o out_even [-o out_odd] -C 0xADDR -D[C] 0xADDR -pi");
- puts(";Convert Amiga executable files into binary files");
- exit(1);
- }
-
- for (i = 1; i < ac; ++i) {
- char *ptr = av[i];
- char *dummy;
-
- if (*ptr != '-') {
- inFile = ptr;
- continue;
- }
- ptr += 2;
- switch(ptr[-1]) {
- case 'o':
- if (*ptr == 0)
- ptr = av[++i];
-
- if (outFile1 == NULL) {
- outFile1 = ptr;
- } else if (outFile2 == NULL) {
- outFile2 = ptr;
- } else {
- puts("Only two image files may be specified");
- exit(1);
- }
- break;
- case 'p': /* -pi */
- PIOpt = 1; /* position independant */
- break;
- case 'C':
- if (*ptr == 0)
- ptr = av[++i];
- CodeStart = strtol(ptr, &dummy, 0);
- CodeStartSpecified = 1;
- break;
- case 'D':
- if (*ptr == 'C') {
- DataStartSpecified = 1;
- DataStartAfterCode = 1;
- break;
- }
- if (*ptr == 0)
- ptr = av[++i];
- DataStart = strtol(ptr, &dummy, 0);
- DataStartSpecified = 1;
- break;
- default:
- printf("Bad option: %s\n", av[i]);
- exit(1);
- }
- }
- if (i > ac) {
- puts("Expected argument");
- exit(1);
- }
- if (PIOpt) {
- DataStart = 0; /* all relative accesses */
- CodeStart = 0;
- DataStartSpecified = 1;
- CodeStartSpecified = 1;
- } else {
- if (DataStartSpecified == 0 || CodeStartSpecified == 0) {
- puts("-D and/or -C options not specified!");
- exit(1);
- }
- }
- if (inFile == NULL) {
- puts("Expected input file");
- exit(1);
- }
- if (outFile1 == NULL) {
- puts("Expected output file");
- exit(1);
- }
- fi = fopen(inFile, "r");
- if (fi == NULL) {
- printf("Unable to open input file %s\n",inFile);
- exit(1);
- }
- if (fgetl(fi) != 0x3F3) {
- printf("%s is not an executable",inFile);
- exit(1);
- }
-
- /*
- * skip name
- */
- {
- int n = fgetl(fi);
- while (n--)
- fgetl(fi);
- }
-
- /*
- * header info
- */
-
- NumHunks = fgetl(fi);
- FirstHunk = fgetl(fi);
- LastHunk = fgetl(fi);
-
- Hunks = malloc(NumHunks * sizeof(Hunk));
- if (Hunks == NULL) {
- puts("malloc failed");
- exit(1);
- }
- LoadHeaderInfo(fi);
- {
- long pos = ftell(fi);
- D(puts("--scan--"));
-
- ScanHunks(fi);
-
- fseek(fi, pos, 0);
- D(puts("--reloc--"));
-
- RelocHunks(fi);
- }
- fclose(fi);
-
- fo1 = fopen(outFile1, "w");
- if (fo1 == NULL) {
- printf("Unable to open output file %s\n", outFile1);
- exit(1);
- }
- if (outFile2) {
- fo2 = fopen(outFile2, "w");
- if (fo2 == NULL) {
- printf("Unable to open output file %s\n", outFile2);
- fclose(fo1);
- remove(outFile1);
- exit(1);
- }
- }
- D(puts("--dump--"));
- DumpHunks(fo1, fo2);
- fclose(fo1);
- if (fo2)
- fclose(fo2);
- return(0);
- }
-
- void
- LoadHeaderInfo(fi)
- FILE *fi;
- {
- int n;
- Hunk *h;
-
- for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
- h->Len = fgetl(fi) * 4;
- h->Data= malloc(h->Len + 1); /* +1 so can malloc 0 wo/error */
- if (h->Data == NULL) {
- printf("malloc failed [hunk %d,length %ld]\n", n, h->Len);
- exit(1);
- }
- }
- }
-
- long CodePc;
- long DataPc;
-
- /*
- * Determine PC start and TYPE. Read data into preallocated memory.
- */
-
- void
- ScanHunks(fi)
- FILE *fi;
- {
- int n;
- Hunk *h;
-
- n = 0;
- h = Hunks;
- while (n < NumHunks) {
- long len;
- long blen;
- long t = fgetl(fi);
-
- D(printf("Header %08lx\n", t));
-
- switch(t) {
- case 0x3E9: /* CODE */
- case 0x3EA: /* DATA */
- h->Type = t;
- len = fgetl(fi) * 4;
- if (len > h->Len || len < 0) {
- printf("Hunk Error: Text len %ld/%ld\n", len, h->Len);
- exit(1);
- }
- h->Len = len;
- if (fread(h->Data, 1, (size_t)len, fi) != len) {
- puts("Unexpected EOF");
- exit(1);
- }
- break;
- case 0x3EB: /* BSS */
- D(printf("BSS Length=%d\n",h->Len));
- h->Type = t;
- setmem(h->Data, h->Len, 0);
- if ((blen=(fgetl(fi)*4)) != h->Len)
- printf("Size mismatch on BSS hunk #%d: %ld != %ld\n",n,blen,h->Len);
- break;
- case 0x3EC: /* HUNK_RELOC32 */
- while ((len = fgetl(fi) * 4) != 0) {
- D(printf("Reloc 32 len = %d\n", len));
- fgetl(fi); /* skip hunk# */
- fseek(fi, len, 1);
- }
- break;
- case 0x3F0: /* SYMBOLS */
- /*
- * ignore
- */
- while ((len = fgetl(fi)) != 0) {
- ubyte type = len >> 24;
-
- len &= 0x00FFFFFF;
- fseek(fi, len * 4, 1);
-
- switch(type) {
- case 0: /* SYMB */
- case 1: /* DEF */
- case 2: /* ABS */
- case 3: /* RES */
- fgetl(fi);
- break;
- case 130: /* COMMON */
- puts("COMMON symbol not supported");
- fgetl(fi); /* skip common size */
- /* fall through */
- case 129: /* REF32 */
- case 131: /* REF16 */
- case 132: /* REF8 */
- case 134: /* REF16D */
- /* skip relocation info */
- fseek(fi, fgetl(fi) * 4 + 4, 1);
- break;
- default:
- printf("Symbol type %d unknown\n", type);
- exit(1);
- }
- }
- break;
- case 0x3F2: /* ignore HUNK_END */
- ++n;
- ++h;
- break;
- default:
- printf("Hunk type %08lx unknown\n", (unsigned long)h->Type);
- exit(1);
- }
- }
-
-
- CodePc = CodeStart;
-
- /*
- * Calculate CODE PC's (base of each hunk, based on size of other hunks)
- */
- for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
- if (h->Type == 0x3E9) {
- D(printf("Code hunk: CodePc=%lx\n",CodePc));
- h->Pc = CodePc;
- CodePc += h->Len;
- }
- }
- D(printf("Code end : CodePc=%lx\n",CodePc));
-
- /*
- * DATA PC's. If -DC (data start after code) is specified then
- * jam the now determined address in (no duplication
- * of data occurs in this case)
- */
- if (DataStartAfterCode)
- DataStart = CodePc;
-
- DataPc = DataStart;
-
- for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
- if (h->Type == 0x3EA) {
- D(printf("Data hunk: DataPc=%lx\n",DataPc));
- h->Pc = DataPc;
- DataPc += h->Len;
- CodePc += h->Len;
- }
- }
-
- /*
- * Start BSS at the end of data
- */
- for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
- if (h->Type == 0x3EB) {
- D(printf("BSS hunk : DataPc=%lx\n",DataPc));
- h->Pc = DataPc;
- DataPc += h->Len;
- }
- }
- D(printf("Data/BSS end : DataPc=%lx\n",DataPc));
- }
-
- void
- RelocHunks(fi)
- FILE *fi;
- {
- int n;
- int dhno;
- Hunk *h;
- Hunk *dh;
-
- n = 0;
- h = Hunks;
-
- while (n < NumHunks) {
- long len;
- long t;
-
- t = fgetl(fi);
- switch(t) {
- case 0x3EB: /* BSS */
- fgetl(fi); /* skip length */
- break;
- case 0x3E9: /* CODE */
- case 0x3EA: /* DATA */
- len = fgetl(fi) * 4;
- fseek(fi, len, 1);
- break;
- case 0x3EC: /* HUNK_RELOC32 */
- if (PIOpt) {
- puts("32 bit relocations exist, cannot make position independant!");
- exit(1);
- }
- while ((len = fgetl(fi)) != 0) {
- dhno = fgetl(fi); /* hunk to relocate to */
- if (dhno < FirstHunk || dhno >= NumHunks + FirstHunk) {
- printf("hunk# in reloc32 bad: %d/%ld\n", dhno, NumHunks);
- exit(1);
- }
- dh = Hunks + dhno - FirstHunk;
- while (len) { /* offsets to relocate */
- long off = fgetl(fi);
-
- if (off < 0 || off > h->Len - 4) {
- printf("Bad offset: %ld len=%ld\n", off, h->Len);
- exit(1);
- }
- *(long *)(h->Data + off) = ToMsbOrder(FromMsbOrder(*(long *)(h->Data + off)) + dh->Pc);
- D(printf("Reloc in %d to %d offset %d add %04x\n", n, dhno, off, dh->Pc));
- --len;
- }
- }
- break;
- case 0x3F0: /* SYMBOLS */
- /*
- * ignore
- */
- while ((len = fgetl(fi)) != 0) {
- ubyte type = len >> 24;
-
- len &= 0x00FFFFFF;
- fseek(fi, len * 4, 1);
-
- switch(type) {
- case 0: /* SYMB */
- case 1: /* DEF */
- case 2: /* ABS */
- case 3: /* RES */
- fgetl(fi);
- break;
- case 130: /* COMMON */
- puts("COMMON symbol not supported");
- fgetl(fi); /* skip common size */
- /* fall through */
- case 129: /* REF32 */
- case 131: /* REF16 */
- case 132: /* REF8 */
- case 134: /* REF16D */
- /* skip relocation info */
- fseek(fi, fgetl(fi) * 4 + 4, 1);
- break;
- default:
- printf("Symbol type %d unknown\n", type);
- exit(1);
- }
- }
- break;
- case 0x3F2: /* ignore HUNK_END */
- ++n;
- ++h;
- break;
- default:
- printf("Hunk type %08lx unknown\n", (unsigned long)h->Type);
- exit(1);
- }
- }
- }
-
- /*
- * Dump the stuff. CODE is first, then DATA and finally BSS (yay!)
- */
- void
- DumpHunks(fo1, fo2)
- FILE *fo1;
- FILE *fo2;
- {
- long endpc = CodeStart;
- short n;
- short nextIsEven = 1;
- Hunk *h;
-
- for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
- if (h->Type == 0x3E9) {
- D(printf("$%04x bytes text @ %08lx\n", h->Len, h->Pc));
- endpc = h->Pc + h->Len;
- if (fo2) {
- nextIsEven = fwrite_2(nextIsEven, fo1, fo2, h->Data, h->Len);
- } else {
- fwrite(h->Data, 1, h->Len, fo1);
- }
- }
- }
-
- for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
- if (h->Type == 0x3EA) {
- D(printf("$%04x bytes data @ %08lx reloc to %08lx\n", h->Len, endpc, h->Pc));
- endpc = h->Pc + h->Len;
- if (fo2) {
- nextIsEven = fwrite_2(nextIsEven, fo1, fo2, h->Data, h->Len);
- } else {
- fwrite(h->Data, 1, h->Len, fo1);
- }
- }
- }
-
- #ifdef BSS_IN_OUTPUT_FILE
- for (n = 0, h = Hunks; n < NumHunks; ++n, ++h) {
- if (h->Type == 0x3EB) {
- D(printf("$%04x bytes bss @ %08lx reloc to %08lx\n", h->Len, endpc, h->Pc));
- endpc = h->Pc + h->Len;
- if (fo2) {
- nextIsEven = fwrite_2(nextIsEven, fo1, fo2, h->Data, h->Len);
- } else {
- fwrite(h->Data, 1, h->Len, fo1);
- }
- }
- }
- D(printf("End at $%08lx\n", endpc));
- #endif
-
- }
-
-
- long
- fgetl(fi)
- FILE *fi;
- {
- long v;
-
- v = getc(fi) << 24;
- v |= getc(fi) << 16;
- v |= getc(fi) << 8;
- v |= getc(fi);
-
- if (feof(fi)) {
- puts("Unexpected EOF");
- exit(1);
- }
- /* D(printf("get %08x\n", v)); */
- return(v);
- }
-
- int
- fwrite_2(nextIsEven, fo_even, fo_odd, ptr, len)
- int nextIsEven;
- FILE *fo_even;
- FILE *fo_odd;
- char *ptr;
- long len;
- {
- while (len--) {
- if (nextIsEven)
- putc(*ptr, fo_even);
- else
- putc(*ptr, fo_odd);
- nextIsEven = 1 - nextIsEven;
- ++ptr;
- }
- return(nextIsEven);
- }
-